/**
 * @param {character[]} keys
 * @param {string[]} values
 * @param {string[]} dictionary
 */
 var Encrypter = function(keys, values, dictionary) {
  this.keys = keys
  this.values = values
  this.dictionary = new Set(dictionary)
  const mp = new Map()
  for(let i = 0; i<keys.length; i++) {
    if(!mp.has(keys[i])) {
      mp.set(keys[i], [])
    }
    mp.get(keys[i]).push(i)
  }
  this.mp = mp
  const val = new Map()
  for(let i = 0; i<values.length; i++) {
    if(!val.has(values[i])) {
      val.set(values[i], [])
    }
    val.get(values[i]).push(i)
  }
  this.val = val
};

/** 
 * @param {string} word1
 * @return {string}
 */
Encrypter.prototype.encrypt = function(word1) {
  const ret = word1.split('')
  for(let i = 0; i<word1.length; i++) {
    const ch = word1[i]
    const arr = this.mp.get(ch)
    for(let j of arr) {
      ret[i] = this.values[j]
    }
  }
  return ret.join('')
};

/** 
 * @param {string} word2
 * @return {number}
 */
Encrypter.prototype.decrypt = function(word2) {
  const val = this.val, keys = this.keys
  const dic = this.dictionary
  let ret = [], temp = [], next = []
  for(let i = 0; i<word2.length; i+=2){
    let c = word2[i] + word2[i+1]
    if(val.has(c)) {
      for(let idx of val.get(c) || []) {
        temp.push(keys[idx])
      }
    } else {
      temp.push(c)
    }
    if(ret.length === 0) {
      ret = temp
      temp = []
      continue
    }
    for(let x of ret) {
      for(let ch of temp) {
        next.push(x+ch)
      }
    }
    ret = next
    temp = []
    next = []
  }
  let ans = 0
  for(let s of ret) {
    if(dic.has(s)) ans++
  }
  return ans
};

/**
 * Your Encrypter object will be instantiated and called as such:
 * var obj = new Encrypter(keys, values, dictionary)
 * var param_1 = obj.encrypt(word1)
 * var param_2 = obj.decrypt(word2)
 */